package com.authine.cloudpivot.ext.applicationservice;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapBuilder;
import cn.hutool.json.JSONUtil;
import com.alibaba.cola.dto.MultiResponse;
import com.alibaba.cola.dto.RequestContext;
import com.alibaba.cola.dto.SingleResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.authine.cloudpivot.ext.Enum.*;
import com.authine.cloudpivot.ext.constants.AppConst;
import com.authine.cloudpivot.ext.constants.ModelConst;
import com.authine.cloudpivot.ext.constants.PlatformConst;
import com.authine.cloudpivot.ext.dto.FinanceReportDto;
import com.authine.cloudpivot.ext.dto.LogisticsInfo;
import com.authine.cloudpivot.ext.dto.base.Ids;
import com.authine.cloudpivot.ext.dto.form.InvoiceApplyForm;
import com.authine.cloudpivot.ext.dto.form.InvoiceApplyUpdateForm;
import com.authine.cloudpivot.ext.dto.model.bill.Bill;
import com.authine.cloudpivot.ext.dto.model.trade.Trade;
import com.authine.cloudpivot.ext.dto.model.golden.GoldenTax;
import com.authine.cloudpivot.ext.dto.model.invoice.*;
import com.authine.cloudpivot.ext.dto.query.BillQuery;
import com.authine.cloudpivot.ext.dto.query.IdType;
import com.authine.cloudpivot.ext.dto.query.InvoiceDetailQuery;
import com.authine.cloudpivot.ext.dto.query.TradeQuery;
import com.authine.cloudpivot.ext.dto.system.OrganizationDto;
import com.authine.cloudpivot.ext.service.bill.BillService;
import com.authine.cloudpivot.ext.service.bill.impl.BillServiceImpl;
import com.authine.cloudpivot.ext.service.goldentax.GoldenTaxService;
import com.authine.cloudpivot.ext.service.goldentax.impl.GoldenTaxServiceImpl;
import com.authine.cloudpivot.ext.service.invoice.InvoiceApplyService;
import com.authine.cloudpivot.ext.service.invoice.InvoiceDetailBillService;
import com.authine.cloudpivot.ext.service.invoice.InvoiceDetailService;
import com.authine.cloudpivot.ext.service.invoice.impl.InvoiceApplyServiceImpl;
import com.authine.cloudpivot.ext.service.invoice.impl.InvoiceDetailBillServiceImpl;
import com.authine.cloudpivot.ext.service.invoice.impl.InvoiceDetailServiceImpl;
import com.authine.cloudpivot.ext.service.settle.SettleService;
import com.authine.cloudpivot.ext.service.settle.impl.SettleServiceImpl;
import com.authine.cloudpivot.ext.service.trade.TradeService;
import com.authine.cloudpivot.ext.service.trade.impl.TradeServiceImpl;
import com.authine.cloudpivot.ext.utils.*;
import com.authine.cloudpivot.ext.utils.system.OrgUtils;
import com.authine.cloudpivot.ext.utils.system.ReportUtils;
import com.authine.cloudpivot.ext.utils.system.SessionUser;
import com.authine.common.util.ObjectMapperUtils;
import com.authine.hermes.app.launcher.service.ApplicationService;
import com.authine.mvp.app.launcher.domain.utills.ApplicationContextUtils;
import com.authine.mvp.app.launcher.dto.bo.response.BOList;
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Maps;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.ws.rs.POST;
import javax.ws.rs.Path;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.authine.hermes.app.launcher.service.ApplicationServiceFoundation.CUSTOM_SERVICE;

@Path("InvoiceApplyController")
@Slf4j
public class InvoiceApplyController extends ApplicationService {

    NamedParameterJdbcTemplate jdbcTemplate =  ApplicationContextUtils.getBean(NamedParameterJdbcTemplate.class);
    TransactionTemplate transactionTemplate =  ApplicationContextUtils.getBean(TransactionTemplate.class);
    public static TradeService tradeService = new TradeServiceImpl();
    public static GoldenTaxService goldenTaxService = new GoldenTaxServiceImpl();

    public static InvoiceDetailService invoiceDetailService = new InvoiceDetailServiceImpl();
    public static InvoiceApplyService invoiceApplyService = new InvoiceApplyServiceImpl();
    public static BillService billService = new BillServiceImpl();

    @Path("pageAvailableApply")
    @POST
    @Operation(summary = "订单维度查询待申请开票", description = "交易维度查询调用平台交易管理的自定义服务", tags = CUSTOM_SERVICE)
    public SingleResponse<BOList> pageAvailableApply(TradeQuery tradeQuery){
        BOList boList = new BOList();
        StringBuffer column = new StringBuffer();
        StringBuffer groupBy;
        Map<String, Object>  param = new HashMap<>();

        if(tradeQuery == null){
            tradeQuery = new TradeQuery();
        }
        tradeQuery.setAllowedInvoiceQuantityStart(BigDecimal.ZERO);
        if (CollectionUtils.isEmpty(tradeQuery.getPlatform_organization_id())) {
            tradeQuery.setPlatform_organization_id(PlatformConst.PLATFORM_ORGANIZATION_IDS);
        }

        String orderColumn;
        if ("VENDOR_ORDER".equals(tradeQuery.getQueryType())) {//供应商销售发票申请单（平台采购发票申请单），订单维度查询
            tradeQuery.setDirection(TradeDirection.Purchase.name());
            column = column.append("direction, customer_order_id, target_organization_name, tax_rate, vendor_order_id, organization_name, organization_id,member_name,")
                    .append(" sum(amount) as amount, sum(allowed_invoice_quantity) as allowed_invoice_quantity,sum(allowed_invoice_total) allowed_invoice_total");
            orderColumn = " order by vendor_order_id desc ";
            groupBy = new StringBuffer(" group by direction, customer_order_id, target_organization_name, tax_rate, vendor_order_id, organization_name, organization_id,member_name ");
        } else {//客户采购发票申请单（平台销售发票申请单）
            tradeQuery.setDirection(TradeDirection.Sale.name());
            column = column.append("direction, customer_order_id,tax_rate,organization_id, organization_name, erp_po, member_name,")
                    .append("  sum(amount) as amount, sum(allowed_invoice_quantity) as allowed_invoice_quantity,sum(allowed_invoice_total) allowed_invoice_total");
            orderColumn = " order by customer_order_id desc ";
            groupBy = new StringBuffer(" group by direction, customer_order_id,tax_rate,organization_id, organization_name, erp_po, member_name ");
        }
        String where = tradeQuery.getWhereSql(param);
        StringBuffer dataSql = new StringBuffer("select ").append(column).append(" from ").append(JdbcTemplateUtils.getTableName(ModelConst.T_TRADE))
                .append(where).append(groupBy);
        StringBuffer countSql = new StringBuffer("select ifnull(count(1), 0) as count from (").append(dataSql).append(") as t");

        log.info("countSql = {}, parameters = {}", countSql, JSONObject.toJSONString(param));
        Integer count = jdbcTemplate.queryForObject(countSql.toString(), param, Integer.class);
        if(count == 0){
            boList.setTotal(0);
            boList.setSchemaCode(ModelConst.T_TRADE);
            return SingleResponse.of(boList);
        }
        String limit = String.format(" limit %s,%s", (tradeQuery.getPageIndex() - 1) * tradeQuery.getPageSize(), tradeQuery.getPageSize());
        dataSql.append(orderColumn).append(limit);
        log.info("dataSql = {}, parameters = {}", dataSql, JSONObject.toJSONString(param));
        List<Trade> trades = JdbcTemplateUtils.queryForPOJOList(dataSql.toString(), param, ModelConst.T_TRADE,Trade.class);
        //如果通过订单商品ID查询，将查询结果通过订单商品ID排序
        if (StringUtils.isNotEmpty(tradeQuery.getOrder_goods_id())) {
            List<Trade> tradeList = new ArrayList<>();
            for (String goodsId : tradeQuery.getOrder_goods_id().split(";")){
                List<Trade> subList = trades.stream().filter(trade -> trade.getOrder_goods_id().equals(goodsId)).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(subList)) {
                    continue;
                }
                tradeList.addAll(subList);
            }
            if (tradeList.size() == trades.size()){
                trades = tradeList;
            }
        }
        //如果是订单维度，需要把金税编码汇总
        if("ORDER".equals(tradeQuery.getQueryType()) || "VENDOR_ORDER".equals(tradeQuery.getQueryType())){
            Set<String> customerOrderIdCollect = trades.stream().map(Trade::getCustomer_order_id).collect(Collectors.toSet());
            List<Trade> trades1 = JdbcTemplateUtils.builder(ModelConst.T_TRADE).selectField("*").in("customer_order_id", customerOrderIdCollect)
                    .eq("direction", TradeDirection.Sale.name())
                    .queryForPOJOList(Trade.class);
            trades.forEach(item -> {
                List<Trade> tradeEntities = trades1.stream().filter(t -> t.getCustomer_order_id().equals(item.getCustomer_order_id())).distinct().collect(Collectors.toList());

                Set<String> goldenTaxCollect = tradeEntities.stream().map(Trade::getGolden_tax).collect(Collectors.toSet());
                item.setGolden_tax(StringUtils.join(goldenTaxCollect, ","));
            });
        }
        boList.setTotal(count);
        boList.setSchemaCode(ModelConst.T_TRADE);
        boList.setData(JSON.parseObject(JSON.toJSONString(trades), List.class));
        return SingleResponse.of(boList);
    }

    @Path("viewCanInvoice")
    @POST
    @Operation(summary = "平台销售发票申请单-待申请-申请开票", description = "待申请开票订单或交易申请开票查询功能，多个待申请开票页面共用", tags = CUSTOM_SERVICE)
    public SingleResponse<List<ApplyInvoiceDetailDto>>  viewCanInvoice(IdType idType){

        Assert.notNull(idType,"查询条件不能为空");
        if (OriginIDType.Trade != idType.getWays()){
            Assert.notNull(idType.getDirection(), "交易方向不能为空");
        }
        Assert.notNull(idType.getIds(), "申请开票的IDS不能为空");
        List<ApplyInvoiceDetailDto> canApplyInvoice = invoiceApplyService.viewCanInvoice(idType);
        return SingleResponse.of(canApplyInvoice);
    }

    @Path("createInvoiceApply")
    @POST
    @Operation(summary = "发票待申请-申请开票-保存（保存并提交）", description = "平台销售发票申请单，平台采购发票申请单功能的申请开票功能", tags = CUSTOM_SERVICE)
    public SingleResponse createInvoiceApply(List<InvoiceApplyForm> invoiceApplyFormList){
        return transactionTemplate.execute(status -> {
            List<String> invoiceIds = invoiceApplyService.createProductInvoice(invoiceApplyFormList);
            Assert.isTrue(!CollectionUtils.isEmpty(invoiceIds), "发票申请单创建失败");
            boolean ifSubmit = invoiceApplyFormList.get(0).isSubmit();
            if (ifSubmit) {
                SingleResponse submit = submitInvoiceApply(Ids.builder().ids(invoiceIds).build());
                if(submit.isSuccess()){
                    return SingleResponse.buildSuccess();
                }else{
                    return SingleResponse.buildFailure("0","发票申请单创建成功，提交失败");
                }
            }
            return SingleResponse.buildSuccess();
        });

    }


    @Path("billPurchaseService")
    @POST
    @Operation(summary = "供应商服务费发票管理-待申请", description = "供应商服务费发票管理-待申请", tags = CUSTOM_SERVICE)
    public MultiResponse billPurchaseService(BillQuery query){
        if (null == query) {
            query = BillQuery.builder().build();
        }
        SessionUser sessionUser = new SessionUser();
        List<String> organizationIds = new ArrayList<>();
        if(!sessionUser.isPm()){
            String currentOrgID = sessionUser.getCurrentOrgID();
            List<OrganizationDto> organizationDtoList = OrgUtils.getOrgListByOrgId(currentOrgID);
            List<String> groupOrgIds = organizationDtoList.stream().map(OrganizationDto::getId).collect(Collectors.toList());

            if(CollectionUtils.isEmpty(query.getOrganization_ids())){
                organizationIds = groupOrgIds;
            }else if(groupOrgIds.containsAll(query.getOrganization_ids())){
                organizationIds = query.getOrganization_ids();
            }else{
                organizationIds = groupOrgIds;
            }
        }
        if (CollectionUtils.isEmpty(organizationIds)) {
            return MultiResponse.buildFailure("-1", "查询的组织不能为空");
        }

        query.setOrganization_ids(organizationIds);
        List<Bill> billList = billService.listServiceFee(query);
        return MultiResponse.of(billList, billList.size());
    }

    @Path("createServiceInvoiceApply")
    @POST
    @Operation(summary = "供应商服务费发票管理-待申请-申请收票", description = "", tags = CUSTOM_SERVICE)
    public SingleResponse createServiceInvoiceApply(List<InvoiceApplyForm> invoiceApplyFormList){
        SingleResponse execute = transactionTemplate.execute(status -> {
            List<String> serviceInvoice = invoiceApplyService.createServiceInvoice(invoiceApplyFormList);
            if(serviceInvoice.size() == 0){
                return SingleResponse.buildFailure("-1", "服务费发票申请失败");
            }
            return SingleResponse.buildSuccess();
        });
        return execute;
    }


    @Path("submitInvoiceApply")
    @POST
    @Operation(summary = "平台销售(采购)发票申请单-提交", description = "提交开票申请（发票申请单页面），数据结构：[id,id]", tags = CUSTOM_SERVICE)
    public SingleResponse submitInvoiceApply(Ids invoiceIds){
        Assert.isTrue(invoiceIds != null, "发票申请单编号为空");
        SingleResponse execute = transactionTemplate.execute(status -> {
            invoiceApplyService.submit(invoiceIds.getIds());
            return SingleResponse.buildSuccess();
        });
        return execute;

    }

    @Path("approveInvoice")
    @POST
    @Operation(summary = "平台销售发票申请单-全部-审批", description = "平台销售（采购）发票申请单-审批发票", tags = CUSTOM_SERVICE)
    public SingleResponse approveInvoice(InvoiceApprove approve){
        log.info("==============请求参数" + JSON.toJSONString(approve));
        return transactionTemplate.execute(status -> {
            Assert.notNull(approve.getStatus(), "审批状态不能为空");
            invoiceApplyService.approveInvoice(approve);
            return SingleResponse.buildSuccess();
        });
    }

    @Path("invoiceDetailList")
    @POST
    @Operation(summary = "平台销售发票申请单-发票明细", description = "返回开票明细模型字段", tags = CUSTOM_SERVICE)
    public SingleResponse<BOList> invoiceDetailList(InvoiceDetailQuery invoiceDetailQuery){
        log.info("==============开票明细查询参数" + JSON.toJSONString(invoiceDetailQuery));
        BOList boList = new BOList();
        StringBuffer dataSql = new StringBuffer("select detail.id,detail.invoice_apply_id,detail.offset_id,detail.trade_id,detail.price,detail.gross_price,detail.amount,")
                .append(" detail.total,detail.tax,detail.tax_rate,detail.`name`,detail.quantity,")
                .append(" trade.customer_order_id,trade.order_goods_id,trade.erp_po,trade.quantity trade_quantity,")
                .append(" apply.number,apply.statuss invoice_apply_statuss,apply.purchase_organization_name organization_name")
                .append(" from i_financialcenter_t_invoice_detail as detail")
                .append(" LEFT JOIN i_financialcenter_t_invoice_apply as apply on detail.invoice_apply_id = apply.id")
                .append(" LEFT JOIN i_financialcenter_t_trade as trade on trade.id = detail.trade_id")
                .append(" where detail.deleted = 0");
        MapBuilder<String, Object> mapBuilder = MapBuilder.create(new HashMap<>());

        if (StringUtils.isNotBlank(invoiceDetailQuery.getInvoice_apply_statuss())){
            dataSql.append(" and apply.statuss = :invoiceApplyStatus");
            mapBuilder.put("invoiceApplyStatus", invoiceDetailQuery.getInvoice_apply_statuss());
        }
        if(StringUtils.isNotBlank(invoiceDetailQuery.getNumber())){
            dataSql.append(" and apply.number = :number");
            mapBuilder.put("number", invoiceDetailQuery.getNumber());
        }
        if(StringUtils.isNotBlank(invoiceDetailQuery.getErp_po())){
            dataSql.append(" and trade.erp_po = :erp_po");
            mapBuilder.put("erp_po", invoiceDetailQuery.getErp_po());
        }
        if(StringUtils.isNotBlank(invoiceDetailQuery.getOrganization_name())){
            dataSql.append(" and apply.purchase_organization_name = :purchase_organization_name");
            mapBuilder.put("purchase_organization_name", invoiceDetailQuery.getOrganization_name());
        }
        if(StringUtils.isNotBlank(invoiceDetailQuery.getSale_organization_id())){
            dataSql.append(" and JSON_UNQUOTE(apply.sale_organization_id ->'$.id') in (:sale_organization_id)");
            mapBuilder.put("sale_organization_id", invoiceDetailQuery.getSale_organization_id().split(";"));
        }else{
            dataSql.append(" and JSON_UNQUOTE(apply.sale_organization_id ->'$.id') in (:sale_organization_id)");
            mapBuilder.put("sale_organization_id", PlatformConst.PLATFORM_ORGANIZATION_IDS);
        }

        if(StringUtils.isNotBlank(invoiceDetailQuery.getCustomer_order_id())){
            dataSql.append(" and trade.customer_order_id = :customer_order_id");
            mapBuilder.put("customer_order_id", invoiceDetailQuery.getCustomer_order_id());
        }
        if(StringUtils.isNotBlank(invoiceDetailQuery.getOrder_goods_id())){
            dataSql.append(" and trade.order_goods_id = :order_goods_id");
            mapBuilder.put("order_goods_id", invoiceDetailQuery.getOrder_goods_id());
        }
        StringBuffer countSql = new StringBuffer("select ifnull(count(1), 0) count from (")
                .append(dataSql).append(" ) as temp");
        log.info("countSql = {}, parameters = {}", countSql, JSONObject.toJSONString(mapBuilder.build()));
        Integer count = jdbcTemplate.queryForObject(countSql.toString(), mapBuilder.build(), Integer.class);
        boList.setTotal(count);
        if (count == 0){
            return SingleResponse.of(boList);
        }
        dataSql.append(" order by detail.id desc");
        String limit = String.format(" limit %s,%s", (invoiceDetailQuery.getPageIndex() - 1) * invoiceDetailQuery.getPageSize(), invoiceDetailQuery.getPageSize());
        dataSql.append(limit);
        log.info("dataSql = {}, parameters = {}", dataSql, JSONObject.toJSONString(mapBuilder.build()));
        List<Map<String,Object>> result = jdbcTemplate.queryForList(dataSql.toString(), mapBuilder.build());
        boList.setData(result);
        boList.setSchemaCode(ModelConst.T_INVOICE_DETAIL);
        return SingleResponse.of(boList);
    }

    /**
     * 拒绝开票
     * @param ids
     * @return
     */
    @Path("rejectionInvoiceApply")
    @POST
    @Operation(summary = "拒绝开票-发票申请单待开票", description = "发票申请单待开票-拒绝开票，数据结构：[id,id]", tags = CUSTOM_SERVICE)
    public SingleResponse rejectionInvoiceApply(Ids ids){
        try{

            if (CollectionUtils.isEmpty(ids.getIds())) {
                return SingleResponse.buildFailure("0","发票申请单编号不能为空");
            }
            //通过id查询待开票的申请
            List<InvoiceApply> invoiceApplyList = JdbcTemplateUtils.builder(ModelConst.T_INVOICE_APPLY).selectField("*")
                    .eq("statuss", InvoiceStatus.DrawerConfirming.name())
                    .in("id", ids.getIds())
                    .queryForPOJOList(InvoiceApply.class);
            if (CollectionUtils.isEmpty(invoiceApplyList)) {
                return SingleResponse.buildFailure("-1","只能拒绝待开票的发票申请单");
            }

            //拒绝开票-修改开票申请单状态
            Map<String, Object> updateParam = new HashMap<>();
            List<String> invoiceApplyIds = invoiceApplyList.stream().map(InvoiceApply::getId).collect(Collectors.toList());
            String updateInvoiceApplySql = "update "+JdbcTemplateUtils.getTableName(ModelConst.T_INVOICE_APPLY)+" set statuss = :statuss, golden_tax_id = null  where deleted = 0 and id in (:ids)";
            updateParam.put("ids", invoiceApplyIds);
            updateParam.put("statuss", InvoiceStatus.New.name());//拒绝的开票申请状态改为新建
            jdbcTemplate.update(updateInvoiceApplySql, updateParam);

            //拒绝开票-开票申请单有金税编码的删除金税开票表记录和明细
            List<String> golden_tax_ids = invoiceApplyList.stream().filter(t -> !ObjectUtils.isEmpty(t.getGolden_tax_id())).map(m -> m.getGolden_tax_id()).collect(Collectors.toList());
            goldenTaxService.delete(golden_tax_ids);
        }catch (IllegalArgumentException e){
            log.error("拒绝开票失败："+ JSONUtil.toJsonStr(ids), e);
            return SingleResponse.buildFailure("0",e.getMessage());
        }
        return SingleResponse.buildSuccess();
    }

    /**
     * 拒绝开票
     * @param ids
     * @return
     */
    @Path("rejectionReceiveInvoice")
    @POST
    @Operation(summary = "平台采购发票申请单-待收票-拒绝收票", description = "数据结构：[id,id]", tags = CUSTOM_SERVICE)
    public SingleResponse rejectionReceiveInvoice(Ids ids){
        try{
            if (CollectionUtils.isEmpty(ids.getIds())) {
                return SingleResponse.buildFailure("0","发票申请单编号不能为空");
            }
            //通过id查询待开票的申请
            List<InvoiceApply> invoiceApplyList = JdbcTemplateUtils.builder(ModelConst.T_INVOICE_APPLY).selectField("*")
                    .eq("statuss", InvoiceStatus.ReceiverConfirming.name())
                    .in("id", ids.getIds())
                    .queryForPOJOList(InvoiceApply.class);
            if (CollectionUtils.isEmpty(invoiceApplyList)) {
                return SingleResponse.buildFailure("-1","只能拒绝待收票的发票申请单");
            }

            //拒绝开票-修改开票申请单状态
            Map<String, Object> updateParam = new HashMap<>();
            List<String> invoiceApplyIds = invoiceApplyList.stream().map(InvoiceApply::getId).collect(Collectors.toList());
            String updateInvoiceApplySql = "update "+JdbcTemplateUtils.getTableName(ModelConst.T_INVOICE_APPLY)+" set statuss = :statuss where deleted = 0 and id in (:ids)";
            updateParam.put("ids", invoiceApplyIds);
            updateParam.put("statuss", InvoiceStatus.DrawerConfirming.name());//回退到待开票
            jdbcTemplate.update(updateInvoiceApplySql, updateParam);

            //回退金税开票表
            List<String> golden_tax_ids = invoiceApplyList.stream().filter(t -> !ObjectUtils.isEmpty(t.getGolden_tax_id())).map(m -> m.getGolden_tax_id()).collect(Collectors.toList());
            JdbcTemplateUtils.builder(ModelConst.T_GOLDEN_TAX)
                    .putFieldAndVal("statuss", InvoiceStatus.DrawerConfirming.name())
                    .in("id", golden_tax_ids)
                    .update();
        }catch (IllegalArgumentException e){
            log.error("拒绝开票失败："+ JSONUtil.toJsonStr(ids), e);
            return SingleResponse.buildFailure("-1",e.getMessage());
        }
        return SingleResponse.buildSuccess();
    }

    /**
     * 取消、作废发票申请单
     */
    @Path("closeInvoiceApply")
    @POST
    @Operation(summary = "平台销售发票申请单-全部-取消（作废）发票申请单", description = "发票申请单页面上面的（取消和作废）按钮，数据结构：[id,id]", tags = CUSTOM_SERVICE)
    public SingleResponse closeInvoiceApply(Ids ids){
        try {
            //审核中，待开票，待收票，已开票
            List<InvoiceStatus> statuss = Arrays.asList(InvoiceStatus.Approving,InvoiceStatus.DrawerConfirming, InvoiceStatus.ReceiverConfirming, InvoiceStatus.Done);
            invoiceApplyService.close(ids.getIds(), statuss);

        }catch (IllegalArgumentException e){
            return SingleResponse.buildFailure("0",e.getMessage());
        }
        return SingleResponse.buildSuccess();
    }

    @Path("deleteInvoiceApply")
    @POST
    @Operation(summary = "平台采购发票申请单-待提交-删除", description = "平台采购发票申请单-待提交-删除", tags = CUSTOM_SERVICE)
    public SingleResponse deleteInvoiceApply(Ids ids){
        log.info("============平台采购发票申请单-待提交-删除===="+JSON.toJSONString(ids));
        try {
            List<InvoiceApply> invoiceApplyList = JdbcTemplateUtils.builder(ModelConst.T_INVOICE_APPLY).selectField("*")
                    .in("id", ids.getIds())
                    .in("statuss", Arrays.asList(InvoiceStatus.New.name(), InvoiceStatus.Returned.name()))
                    .queryForPOJOList(InvoiceApply.class);
            Assert.isTrue(!CollectionUtils.isEmpty(invoiceApplyList), "未获取到对应的发票申请单");
            for (InvoiceApply invoiceApply : invoiceApplyList){
                BoServiceUtils.deleteBo( ModelConst.T_INVOICE_APPLY, invoiceApply.getId(),true);
            }
            invoiceDetailService.deleteInvoiceDetail(null, invoiceApplyList.stream().map(InvoiceApply::getId).collect(Collectors.toList()));
        }catch (IllegalArgumentException e){
            return SingleResponse.buildFailure("0", e.getMessage());
        }
        return SingleResponse.buildSuccess();
    }



    /**
     * 批量反写
     * @return
     */
    @Path("goldenTaxWriteBack")
    @POST
    @Operation(summary = "发票申请单批量反写", description = "发票申请单列表，待开票上面的批量反写功能", tags = CUSTOM_SERVICE)
    public Map<String, Object> goldenTaxWriteBack(){
        return goldenTaxConfirmInvoice(new Ids());
    }

    /**
     * 金税接口开票回写，仅用于根据金税反写的数据进行确认开票（定时、页面手动触发）
     *
     * @param ids 回写的发票id
     */
    @Path("goldenTaxConfirmInvoice")
    @POST
    @Operation(summary = "确认开票(点击按钮调用)", description = "确认开票(点击按钮调用),只能单笔操作，但是需要传值ids", tags = CUSTOM_SERVICE)
    public Map<String, Object> goldenTaxConfirmInvoice(Ids ids){
        boolean ifSpecify = true;
        List<String> invoiceIds = ids.getIds();
        List<InvoiceApply> goldenTaxResult;
        //查询待开票数据
        StringBuffer sql = new StringBuffer(" select * from "+ JdbcTemplateUtils.getTableName(ModelConst.T_INVOICE_APPLY) +" where statuss='DrawerConfirming' and golden_tax_id is not null ");
        if (CollectionUtils.isEmpty(invoiceIds)) {
            goldenTaxResult = JdbcTemplateUtils.queryForPOJOList(sql.toString(), new HashMap<>(), ModelConst.T_INVOICE_APPLY, InvoiceApply.class);
        } else {
            sql.append(" and id in (:ids)");
            goldenTaxResult = JdbcTemplateUtils.queryForPOJOList(sql.toString(), Maps.newHashMap("ids", invoiceIds), ModelConst.T_INVOICE_APPLY, InvoiceApply.class);
        }
        if (goldenTaxResult.size()==0){
            return Maps.newHashMap("1", "金税接口开票成功");
        }
        List<String> goldenTaxIds = goldenTaxResult.stream().map(InvoiceApply::getGolden_tax_id).collect(Collectors.toList());

        //金税开票记录
        List<GoldenTax> goldenTaxList = goldenTaxService.listDone(goldenTaxIds);
        if(CollectionUtils.isEmpty(goldenTaxList)){//没有开票成功的信息
            return Maps.newHashMap("1", "成功");
        }
        //确认收票的申请单列表
//        List<InvoiceApply> confirmInvoiceList = new ArrayList<>();

        for (GoldenTax goldenTax : goldenTaxList){
            InvoiceApply invoiceApply = goldenTaxResult.stream().filter(t -> goldenTax.getId().equals(t.getGolden_tax_id())).findAny().orElseThrow(IllegalArgumentException::new);
            InvoiceRecord invoiceRecord = InvoiceRecord.builder().build()
                    .setCode(goldenTax.getCode())
                    .setNumber(goldenTax.getNumber())
                    .setPretax_amount(goldenTax.getPrice_amount())
                    .setTax_payable(goldenTax.getTax_amount());
            MakeInvoice makeInvoice = MakeInvoice.builder().build()
                    .setId(invoiceApply.getId())
                    .setDrawer(goldenTax.getDrawer())
                    .setOrderType(invoiceApply.getOrder_type())
                    .setDate(goldenTax.getInvoice_time())
                    .setInvoiceApplyRecordList(Collections.singletonList(invoiceRecord))
                    .setDrawer_member_id(RequestContext.getCorpLoginId())
                    .setDrawer_member_name(RequestContext.getLoginRealName());
            //确认开票
            confirmInvoice(makeInvoice);

            ConfirmInvoice confirmInvoice = ConfirmInvoice.builder().build()
                    .setId(invoiceApply.getId())
                    .setRecipient_member_id(RequestContext.getCorpLoginId())
                    .setRecipient_member_name(RequestContext.getLoginRealName())
                    .setConfirm_time(goldenTax.getInvoice_time());
            //确认收票
            receiveInvoice(confirmInvoice);

        }
        return Maps.newHashMap("1", "成功");
    }

    /**
     * 确认开票
     *
     * @param makeInvoice 发票申请单编号，发票代码，发票号码，开票人，未税金额，税额，确认开票时间
     * @return
     */
    @Path("confirmInvoice")
    @POST
    @Operation(summary = "确认开票-立即提交", description = "待开票发票确认开票", tags = CUSTOM_SERVICE)
    public SingleResponse confirmInvoice(MakeInvoice makeInvoice) {
        makeInvoice.setDrawer_member_id(RequestContext.getCorpLoginId());
        makeInvoice.setDrawer_member_name(RequestContext.getLoginRealName());
        Assert.notNull(makeInvoice.getId(), "发票ID不能为空");
        Assert.isTrue(StringUtils.isNotBlank(makeInvoice.getDrawer()), "开票人不能为空");
        Assert.notNull(makeInvoice.getDate(), "确认开票时间不能为空");
        SingleResponse execute = transactionTemplate.execute(status -> {
            InvoiceApply invoiceApply = invoiceApplyService.confirmInvoice(makeInvoice);
            //平台销售发票确认开票，自动执行收票操作
            if (PlatformConst.PLATFORM_ORGANIZATION_IDS.contains(invoiceApply.getSale_organization_id().getId())) {
                ConfirmInvoice confirmInvoice = ConfirmInvoice.builder()
                        .id(invoiceApply.getId())
                        .confirm_time(new Date())
                        .build();
                invoiceApplyService.receiveInvoice(confirmInvoice);
            }
            return SingleResponse.buildSuccess();
        });
        return execute;
    }

    /**
     * 确认收票
     *
     * @param confirmInvoice 确认收票
     */
    @Path("receiveInvoice")
    @POST
    @Operation(summary = "确认收票", description = "待收票状态下确认收票", tags = CUSTOM_SERVICE)
    public SingleResponse receiveInvoice(ConfirmInvoice confirmInvoice){
        Assert.notNull(confirmInvoice, "确认收票数据不能为空");
        Assert.notNull(confirmInvoice.getId(), "发票ID不能为空");
        Assert.notNull(confirmInvoice.getConfirm_time(), "收票时间不能为空");
        return transactionTemplate.execute(status -> {
                invoiceApplyService.receiveInvoice(confirmInvoice);
                return SingleResponse.buildSuccess();
            });
    }

    /**
     * 撤销开票
     *
     * @param invoiceIds 需要撤销的发票申请单ID
     */
    @Path("invoiceRollback")
    @POST
    @Operation(summary = "平台销售（采购）发票申请单-已开票-撤销开票（撤销收票）", description = "平台销售发票申请单-已开票-撤销开票", tags = CUSTOM_SERVICE)
    public SingleResponse invoiceRollback(Ids invoiceIds){
        Assert.isTrue(!CollectionUtils.isEmpty(invoiceIds.getIds()),"要回退的发票申请单号不能为空");
        return transactionTemplate.execute(status -> {
            invoiceApplyService.invoiceRollback(invoiceIds.getIds());
            return SingleResponse.buildSuccess();
        });

    }

    @Path("offsetInvoice")
    @POST
    @Operation(summary = "红冲发票", description = "红冲发票", tags = CUSTOM_SERVICE)
    public SingleResponse offsetInvoice(OffsetInvoice offsetInvoice){
        if(offsetInvoice.getId() == null){
           return SingleResponse.buildFailure("0", "发票ID不能为空");
        }
        return transactionTemplate.execute(status -> {
            invoiceApplyService.offsetInvoice(offsetInvoice);
            return SingleResponse.buildSuccess();
        });
    }

    /**
     * 寄送发票
     */
    @Path("logisticsInfo")
    @POST
    @Operation(summary = "寄送发票", description = "寄送发票", tags = CUSTOM_SERVICE)
    public SingleResponse logisticsInfo(LogisticsInfo logisticsInfo){
        Assert.notNull(logisticsInfo, "参数不能为空");
        Assert.notNull(logisticsInfo.getLogisticsInfo(), "物流信息不能为空");

        List<InvoiceApply> invoiceApplyList = JdbcTemplateUtils.builder(ModelConst.T_INVOICE_APPLY).selectField("*")
                .in("id", logisticsInfo.getInvoiceIds())
                .in("statuss", Arrays.asList(InvoiceStatus.ReceiverConfirming.name(), InvoiceStatus.Done.name()))
                .queryForPOJOList(InvoiceApply.class);
        Assert.notEmpty(invoiceApplyList, "发票记录不存在");
        invoiceApplyList.forEach(item -> {
            JdbcTemplateUtils.builder(ModelConst.T_INVOICE_APPLY)
                    .putFieldAndVal("logistic_info", logisticsInfo.getLogisticsInfo())
                    .putFieldAndVal("has_logistic_info", 1)
                    .eq("id", item.getId())
                    .update();

            if (PlatformConst.PLATFORM_ORGANIZATION_IDS.contains(item.getSale_organization_id().getId())
                    && InvoiceStatus.ReceiverConfirming.name().equals(item.getStatuss())) {
                //如果是平台开票，则自动收票
                ConfirmInvoice confirmInvoice = ConfirmInvoice.builder()
                        .id(item.getId())
                        .ifSend(true)
                        .confirm_time(new Date())
                        .build();
                receiveInvoice(confirmInvoice);
            }
        });
        return SingleResponse.buildSuccess();
    }
    /**
     * 修改开票信息
     */
    @Path("updateInvoice")
    @POST
    @Operation(summary = "修改开票信息", description = "修改开票信息", tags = CUSTOM_SERVICE)
    public SingleResponse updateInvoice(InvoiceApplyUpdateForm invoiceDto){
        Assert.notNull(invoiceDto, "修改发票入参不能为空");
        Assert.notNull(invoiceDto.getPurchase_name(), "修改发票抬头不能为空");
        Assert.notNull(invoiceDto.getId(), "发票单编号不能为空");
        invoiceApplyService.updateInvoice(invoiceDto);
        if (invoiceDto.isSubmit()){
            submitInvoiceApply(Ids.builder().ids(Collections.singletonList(invoiceDto.getId())).build());
        }
        return SingleResponse.buildSuccess();
    }

    /**
     * 获取平台组织的默认开票信息
     */
    @Path("platformOrgInvoiceInfo")
    @POST
    @Operation(summary = "获取平台组织的默认开票信息", description = "获取平台组织的默认开票信息，id=平台组织ID", tags = CUSTOM_SERVICE)
    public SingleResponse<Map<String, Object>> platformOrgInvoiceInfo(Ids dto){
        Assert.notNull(dto.getId(), "获取的发票的平台组织ID不能为空");
        OrganizationDto org = OrgUtils.getOrgByOrgId(dto.getId());
        if(org !=null && PlatformConst.PLATFORM_ORGANIZATIONS.values().contains(org.getName())){
            String sql = "select m.* from "+ JdbcTemplateUtils.getTableName(ModelConst.T_MEMBER_INVOICE, AppConst.PERSONAL_CENTER) +" m where m.deleted=0 and m.member_id=:memberId and m.tax_number=:taxNumber";
            List<Map<String, Object>> queryForList = new ArrayList<>();
            if(PlatformConst.ORGANIZATION_ACCOUND_ID.equals(org.getId())){//上海固买
               Map<String, Object> map = Maps.newHashMap("memberId", 1);
               map.put("taxNumber", PlatformConst.SHTAXNUM);
                queryForList = jdbcTemplate.queryForList(sql, map);
            }else if(PlatformConst.ORGANIZATION_ACCOUND_ID.equals(org.getId())){//南阳固买
                Map<String, Object> map = Maps.newHashMap("memberId", 1);
                map.put("taxNumber", PlatformConst.NYTAXNUM);
                queryForList = jdbcTemplate.queryForList(sql, map);
            }
            Assert.isTrue(queryForList!=null && queryForList.size()==1, "请联系管理员维护发票信息");
            return SingleResponse.of(queryForList.get(0));
        }else{
            return SingleResponse.buildFailure("-1", "根据入参ID没有查询到平台开票信息");
        }

    }

    /**
     * 平台销售发票申请单-全部-导出查询结果
     */
    @Path("exportInvoiceList")
    @POST
    @Operation(summary = "平台销售发票申请单-全部-导出查询结果", description = "平台采购发票申请单-全部-导出查询结果", tags = CUSTOM_SERVICE)
    public SingleResponse exportInvoiceList(FinanceReportDto reportDto){
        //验证选择导出的报表类型是否正确
        Assert.notNull(reportDto.getReportType(), "导出报表类型异常");
        Assert.notNull(reportDto.getReportName(), "reportName不能为空");

        reportDto.getFilterObj().setPageSize(500);
        SingleResponse<BOList> listBO = super.listBO(reportDto.getFilterObj());
        List<Map<String, Object>> result = listBO.getData().getData();

        List<Map<String, Object>> fileData = result.stream().map(invoice->{
            Map<String, Object> data = new HashMap<>();
            data.put("purchaseName",invoice.get("purchase_name"));
            data.put("drawer",invoice.get("drawer"));
            data.put("recipientMemberName",invoice.get("recipient_member_name"));
            data.put("time",invoice.get("createdTime"));
            data.put("id",invoice.get("id"));
            data.put("code",invoice.get("code"));
            data.put("taxRate",invoice.get("tax_rate"));
            data.put("memberName",invoice.get("member_name"));
            data.put("purchaseOrganizationName",invoice.get("purchase_organization_name"));
            data.put("priceAmount",invoice.get("price_amount"));
            data.put("number",invoice.get("number"));
            data.put("saleOrganizationName",invoice.get("sale_organization_name"));
            data.put("taxAmount",invoice.get("tax_amount"));
            data.put("businessType",invoice.get("business_type"));
            data.put("total",invoice.get("total"));
            data.put("extendsAttr", InvoiceExtendsAttr.conversion(invoice.get("extends_attr").toString()).get());
            data.put("date",invoice.get("date"));
            data.put("status",invoice.get("statuss"));
            data.put("confirmTime",invoice.get("confirm_time"));
            data.put("type",invoice.get("type"));
            data.put("logisticInfo",invoice.get("logistic_info"));
            data.put("goldenTaxId",invoice.get("golden_tax_id"));
            data.put("memo",invoice.get("memo"));
            return data;
        }).collect(Collectors.toList());
        ReportUtils.exportReport(reportDto.getReportName(), reportDto.getReportType().getId(),fileData);
        return SingleResponse.buildSuccess();

    }

    @Path("exportInvoiceApply")
    @POST
    @Operation(summary = "平台销售发票申请单-全部-导出销售发票单", description = "平台销售发票申请单-全部-导出采购发票单", tags = CUSTOM_SERVICE)
    public SingleResponse exportInvoiceApply(FinanceReportDto reportDto){
        //验证选择导出的报表类型是否正确
        Assert.notNull(reportDto.getIds(), "导出发票的ID不能为空");
        Assert.notNull(reportDto.getReportType(), "导出报表类型异常");
        Assert.notNull(reportDto.getReportName(), "reportName不能为空");

        List<InvoiceApply> result = invoiceApplyService.loadListByIds(reportDto.getIds());
        List<InvoiceDetail> invoiceDetailList = JdbcTemplateUtils.builder(ModelConst.T_INVOICE_DETAIL).selectField("*")
                .in("invoice_apply_id", reportDto.getIds())
                .queryForPOJOList(InvoiceDetail.class);

        List<Map<String, Object>> fileData = result.stream().map(invoice->{
            Map<String, Object> data = new HashMap<>();
            //发票信息
            data.put("id", invoice.getId());
            data.put("code", invoice.getCode());
            data.put("type", invoice.getType());
            data.put("number", invoice.getNumber());
            data.put("total", invoice.getTotal());
            data.put("memo", invoice.getMemo());
            data.put("taxAmount", invoice.getTax_amount());
            data.put("priceAmount", invoice.getPrice_amount());
            data.put("saleOrganizationName", invoice.getSale_organization_name());
            data.put("purchaseNumber", invoice.getPurchase_number());
            data.put("purchaseAddress", invoice.getPurchase_address());
            data.put("purchaseName", invoice.getPurchase_name());
            data.put("purchaseAccount", invoice.getPurchase_account());
            data.put("purchasePhone", invoice.getPurchase_phone());
            data.put("applyMemberName", invoice.getApply_member_name());
            data.put("purchaseBank", invoice.getPurchase_bank());

            //明细信息
            List<InvoiceDetail> mappingInvoiceDetailList = invoiceDetailList.stream().filter(t->t.getInvoice_apply_id().equals(invoice.getId())).collect(Collectors.toList());
            List<Trade> tradeList = tradeService.loadListByIds(mappingInvoiceDetailList.stream().map(InvoiceDetail::getTrade_id).collect(Collectors.toList()));
            List<Map<String, Object>> detailList = new ArrayList<>();
            Set<String> vendorOrderIds = new HashSet<>();
            for (InvoiceDetail invoiceDetail : mappingInvoiceDetailList) {
                Trade trade = tradeList.stream().filter(t->t.getId().equals(invoiceDetail.getTrade_id())).findAny().get();
                Map<String, Object> detailMap = new HashMap<>();
                InvoiceDetailExtendsAttr extendsAttr = InvoiceDetailExtendsAttr.conversion(invoiceDetail.getExtends_attr()).get();
                detailMap.put("name", invoiceDetail.getName());
                detailMap.put("modelSpec", invoiceDetail.getModel_spec());
                detailMap.put("quantity", invoiceDetail.getQuantity());
                detailMap.put("unit", invoiceDetail.getUnit());
                detailMap.put("price", invoiceDetail.getPrice());
                detailMap.put("grossPrice", invoiceDetail.getGross_price());
                detailMap.put("total", invoiceDetail.getTotal());
                detailMap.put("amount", invoiceDetail.getAmount());
                detailMap.put("tax", invoiceDetail.getTax());
                detailMap.put("taxRate", invoiceDetail.getTax_rate());
                detailMap.put("trade.taxRate", trade.getTax_rate());
                detailMap.put("goldenTax", invoiceDetail.getGolden_tax());
                detailMap.put("vendorOfferMemo", trade.getMemo());
                detailMap.put("isOil", invoiceDetail.getName().contains("润滑油") || invoiceDetail.getName().contains("润滑脂")
                        || invoiceDetail.getName().contains("齿轮油") || invoiceDetail.getName().contains("切削液"));//是否是油品
                detailMap.put("extendsAttr", extendsAttr);
                vendorOrderIds.add(extendsAttr.getVendorOrderId());
                detailList.add(detailMap);
            }
            data.put("vendorOrderIds", String.join(",", vendorOrderIds));
            data.put("invoiceDetailList", detailList);
            return data;
        }).collect(Collectors.toList());
        ReportUtils.exportReport(reportDto.getReportName(), reportDto.getReportType().getId(),fileData);
        return SingleResponse.buildSuccess();

    }

    @Path("exportInvoiceDetail")
    @POST
    @Operation(summary = "平台销售发票申请单-发票明细-导出查询结果", tags = CUSTOM_SERVICE)
    public SingleResponse exportInvoiceDetail(InvoiceDetailQuery invoiceDetailQuery){
        Assert.notNull(invoiceDetailQuery.getReportType().getId(), "导出报表类型异常");
        Assert.notNull(invoiceDetailQuery.getReportName(), "exportName不能为空");

        invoiceDetailQuery.setPageIndex(1).setPageSize(500);
        SingleResponse<BOList> boListSingleResponse = invoiceDetailList(invoiceDetailQuery);
        List<Map<String, Object>> boList = boListSingleResponse.getData().getData();
        Assert.isTrue(boListSingleResponse.getData().getTotal()>0, "导出数据为空");
        List<Map<String, Object>> fileData = boList.stream().map(detail->{
            Map<String, Object> data = new HashMap<>();
            data.put("id", detail.get("id"));
            data.put("number", detail.get("number"));
            data.put("taxRate", detail.get("tax_rate"));
            data.put("total", detail.get("total"));
            data.put("status", detail.get("invoice_apply_statuss"));
            data.put("invoiceApplyId", detail.get("invoice_apply_id"));
            data.put("offsetId", detail.get("offset_id"));
            data.put("tradeId", detail.get("trade_id"));
            data.put("price", detail.get("price"));
            data.put("quantity", detail.get("quantity"));
            data.put("amount", detail.get("amount"));
            data.put("customerOrderId", detail.get("customer_order_id"));
            data.put("orderGoodsId", detail.get("order_goods_id"));
            data.put("name", detail.get("name"));
            data.put("erpPO", detail.get("erp_po"));
            data.put("organizationName", detail.get("organization_name"));
            data.put("invoiceQuantity", detail.get("trade_quantity"));
            data.put("grossPrice", detail.get("gross_price"));
            return data;
        }).collect(Collectors.toList());
        ReportUtils.exportReport(invoiceDetailQuery.getReportName(), invoiceDetailQuery.getReportType().getId(), fileData);
        return  SingleResponse.buildSuccess();
    }

    @Path("exportPendingInvoice")
    @POST
    @Operation(summary = "平台销售发票申请单-待申请-导出查询结果", description = "平台采购发票申请单-待申请-导出查询结果", tags = CUSTOM_SERVICE)
    public SingleResponse exportPendingInvoice(TradeQuery query){
        Assert.notNull(query.getReportType().getId(), "导出报表类型异常");
        Assert.notNull(query.getReportName(), "exportName不能为空");

        query.setPageIndex(1).setPageSize(Integer.MAX_VALUE);
        List<Trade> tradeList;
        if(StringUtils.isNotBlank(query.getQueryType())){
            tradeList = ObjectMapperUtils.readValue(JSON.toJSONString(pageAvailableApply(query).getData().getData()), Trade.class);
        }else{
            tradeList = tradeService.listTradeByParam(query).getData();
        }
        Assert.isTrue(tradeList.size()>0, "导出数据为空");
        List<Map<String, Object>> fileData = tradeList.stream().map(trade->{
            Map<String, Object> data = new HashMap<>();
            data.put("id", trade.getId());
            data.put("erpPo", trade.getErp_po());
            data.put("organizationName", trade.getOrganization_name());
            data.put("targetOrganizationName", trade.getTarget_organization_name());
            data.put("customerOrderId", trade.getCustomer_order_id());
            data.put("vendorOrderId", trade.getVendor_order_id());
            data.put("price", trade.getPrice());
            data.put("quantity", trade.getQuantity());
            data.put("taxRate", trade.getTax_rate());
            data.put("orderGoodsId", trade.getOrder_goods_id());
            data.put("total", trade.getTotal());
            data.put("invoiceIds", trade.getInvoice_ids());
            data.put("time", trade.getCreatedTime());
            data.put("summary", trade.getSummary());
            data.put("orderGoodsStatusDes", trade.getOrder_goods_status()==null ? "":trade.getOrder_goods_status().des);
            data.put("allowedInvoiceQuantity", trade.getAllowed_invoice_quantity());
            data.put("allowedInvoiceTotal", trade.getAllowed_invoice_total());
            data.put("alreadyInvoiceQuantity", trade.getAlready_invoice_quantity());
            data.put("alreadyInvoiceTotal", trade.getAlready_invoice_total());
            data.put("amount", trade.getAmount());
            data.put("rebateStatus", trade.getTarget_settle_statuss()==null ? "": trade.getTarget_settle_statuss().des);
            return data;
        }).collect(Collectors.toList());
        ReportUtils.exportReport(query.getReportName(), query.getReportType().getId(), fileData);
        return  SingleResponse.buildSuccess();
    }

    @Path("exportInvoiceApplyUnpaid")
    @POST
    @Operation(summary = "平台采购发票申请单-已收票-导出未付款", tags = CUSTOM_SERVICE)
    public SingleResponse exportInvoiceApplyUnpaid(FinanceReportDto dto){
        Assert.notNull(dto.getReportType().getId(), "导出报表类型异常");
        Assert.notNull(dto.getReportName(), "exportName不能为空");

        String sql = "SELECT " +
                " apply.ID ID, " +
                " '已开票' applyStatus, " +
                " SUM( detail.total ) total, " +
                " apply.sale_organization_name organizationName, " +
                " apply.DATE  date, " +
                " apply.confirm_time confirmTime, " +
                " apply.NUMBER number, " +
                " CASE " +
                "  WHEN GROUP_CONCAT( DISTINCT targetTrade.settle_status ) = 'Done' THEN " +
                "  '已回款'  " +
                "  WHEN GROUP_CONCAT( DISTINCT targetTrade.settle_status ) = 'Undo' THEN " +
                "  '未回款' ELSE '部分回款'  " +
                " END rebateStatus  " +
                " FROM " +
                " i_financialcenter_t_invoice_detail_bill detail " +
                " LEFT JOIN i_financialcenter_t_trade trade ON trade.ID = detail.trade_id " +
                " LEFT JOIN ( " +
                " SELECT " +
                "  detail.invoice_detail_bill_id, " +
                "  COUNT( detail.ID ) id  " +
                " FROM " +
                "  i_financialcenter_t_settle_detail detail " +
                "  LEFT JOIN i_financialcenter_t_settle settle ON settle.ID = detail.settle_id  " +
                " WHERE " +
                "  settle.statuss <> 'Returned'  " +
                "  AND settle.deleted = 0  " +
                "  AND detail.deleted = 0  " +
                " GROUP BY " +
                "  detail.invoice_detail_bill_id  " +
                " ) settle ON settle.invoice_detail_bill_id = detail.ID " +
                " LEFT JOIN i_financialcenter_t_invoice_apply apply ON apply.ID = detail.invoice_apply_id " +
                " LEFT JOIN ( SELECT trade.target_order_goods_id, trade.settle_status FROM i_financialcenter_t_trade trade WHERE trade.deleted = 0 AND trade.direction = 'Sale' ) targetTrade ON targetTrade.target_order_goods_id = trade.order_goods_id " +
                " WHERE " +
                " ( settle.ID IS NULL OR settle.ID = 0 )  " +
                " AND trade.direction = 'Purchase'  " +
                " AND detail.offset_total <> detail.total  " +
                " AND apply.business_type = 'Product'  " +
                " AND apply.purchase_organization_id = 1  " +
                " AND detail.deleted = 0  " +
                " AND apply.deleted = 0  " +
                " AND apply.statuss = 'Done'  " +
                " GROUP BY " +
                " apply.ID, " +
                " apply.sale_organization_name, " +
                " apply.DATE, " +
                " apply.confirm_time, " +
                " apply.NUMBER ";
        List<Map<String, Object>> resultMap = JdbcTemplateUtils.queryForList(sql, new HashMap<>());
        List<InvoiceReceivedUnpaidReport> receivedUnpaidReportList = ObjectMapperUtils.readValue(JSON.toJSONString(resultMap), InvoiceReceivedUnpaidReport.class);
        ReportUtils.exportReport(dto.getReportName(), dto.getReportType().getId(), receivedUnpaidReportList.stream().map(BeanUtil::beanToMap).collect(Collectors.toList()));
        return SingleResponse.buildSuccess();
    }

    @Path("exportInvoiceService")
    @POST
    @Operation(summary = "平台服务费发票管理-全部-导出报表", tags = CUSTOM_SERVICE)
    public SingleResponse exportInvoiceService(FinanceReportDto dto){
        Assert.notNull(dto.getReportType().getId(), "导出报表类型异常");
        Assert.notNull(dto.getReportName(), "exportName不能为空");
        List<String> ids = dto.getIds();

        //发票单
        List<InvoiceApply> invoiceApplyList = JdbcTemplateUtils.builder(ModelConst.T_INVOICE_APPLY).selectField("*")
                .in("id", ids)
                .queryForPOJOList(InvoiceApply.class);
        if (invoiceApplyList.size()==0){
            ReportUtils.exportReport(dto.getReportName(), dto.getReportType().getId(), new ArrayList<>());
            return SingleResponse.buildSuccess();
        }
        //发票账单明细
        List<InvoiceDetailBill> invoiceDetailBills = JdbcTemplateUtils.builder(ModelConst.T_INVOICE_DETAIL_BILL).selectField("*")
                .in("invoice_apply_id", invoiceApplyList.stream().map(InvoiceApply::getId).collect(Collectors.toList()))
                .queryForPOJOList(InvoiceDetailBill.class);
        //发票明细
        List<InvoiceDetail> invoiceDetailList = JdbcTemplateUtils.builder(ModelConst.T_INVOICE_DETAIL).selectField("*")
                .in("invoice_apply_id", invoiceApplyList.stream().map(InvoiceApply::getId).collect(Collectors.toList()))
                .queryForPOJOList(InvoiceDetail.class);

        List<InvoiceServiceReport> dataList = new ArrayList<>();
        invoiceApplyList.forEach(invoiceApply->{
            List<InvoiceDetailBill> mappingInvoiceDetailBill = invoiceDetailBills.stream().filter(t->t.getInvoice_apply_id().equals(invoiceApply.getId())).collect(Collectors.toList());
            List<InvoiceDetail> mappingInvoiceDetail = invoiceDetailList.stream().filter(t->t.getInvoice_apply_id().equals(invoiceApply.getId())).collect(Collectors.toList());
            //获取供应商订单编号
            List<String> vendorOrderIds = new ArrayList<>();
            List<String> tradeIds = new ArrayList<>();
            for (InvoiceDetail detail : mappingInvoiceDetail){
                vendorOrderIds.add(InvoiceDetailExtendsAttr.conversion(detail.getExtends_attr()).get().getVendorOrderId());
                tradeIds.add(detail.getTrade_id());
            }
            //通过明细获取交易对应的货物发票号码
            String sql = "select invoice.number from "+ JdbcTemplateUtils.getTableName(ModelConst.T_INVOICE_APPLY) + " as invoice"+
                    " left join " + JdbcTemplateUtils.getTableName(ModelConst.T_INVOICE_DETAIL) +" as detail on invoice.id = detail.invoice_apply_id " +
                    " where detail.deleted = 0 and invoice.business_type = 'Product' and detail.trade_id in (:tradeIds)";
            List<String> number = jdbcTemplate.queryForList(sql, Maps.newHashMap("tradeIds", tradeIds), String.class);
            //垫资服务费
            BigDecimal interest = CalculatorUtils.sum(mappingInvoiceDetailBill.stream().filter(t->t.getBill_type().equals(BillType.FinancialFee.name())).collect(Collectors.toList()),
                    BiFunctionConst.invoiceBillTotalFun);
            //平台费
            BigDecimal platform = CalculatorUtils.sum(mappingInvoiceDetailBill.stream().filter(t->t.getBill_type().equals(BillType.PlatformFee.name())).collect(Collectors.toList()),
                    BiFunctionConst.invoiceBillTotalFun);
            //计算未税
            BigDecimal platformUntaxed = BigDecimalUtils.round(TaxRateUtils.calculateTaxBefore(platform,PlatformConst.PLATTAXRATE),2);
            BigDecimal interestUntaxed = BigDecimalUtils.round(TaxRateUtils.calculateTaxBefore(interest,PlatformConst.PLATTAXRATE),2);
            dataList.add(InvoiceServiceReport.builder()
                    .vendorOrderIds(StringUtils.join(vendorOrderIds, ","))
                    .vendorNumber(String.join(",",number))
                    .id(invoiceApply.getId())
                    .goldenTaxId(invoiceApply.getGolden_tax_id())
                    .purchaseName(invoiceApply.getPurchase_name())
                    .purchaseNumber(invoiceApply.getPurchase_number())
                    .purchaseAddress(invoiceApply.getPurchase_address())
                    .purchasePhone(invoiceApply.getPurchase_phone())
                    .purchaseBank(invoiceApply.getPurchase_bank())
                    .purchaseAccount(invoiceApply.getPurchase_account())
                    .platform(platform.doubleValue())
                    .platformRate(PlatformConst.PLATTAXRATE.doubleValue())
                    .interest(interest.doubleValue())
                    .interestRate(PlatformConst.PLATTAXRATE.doubleValue())
                    .total(interest.add(platform).doubleValue())
                    .platformUntaxed(platformUntaxed.doubleValue())
                    .interestUntaxed(interestUntaxed.doubleValue())
                    .build());
        });
        ReportUtils.exportReport(dto.getReportName(), dto.getReportType().getId(), dataList.stream().map(BeanUtil::beanToMap).collect(Collectors.toList()));
        return SingleResponse.buildSuccess();
    }


}
